import React, { useEffect, useRef, useState } from 'react';
import styled, { keyframes } from 'styled-components';
import { useGame } from '../context/GameContext';
import Snake from './Snake';
import Food from './Food';
import StartMenu from './StartMenu';
import PauseMenu from './PauseMenu';
import ScoreBoard from './ScoreBoard';
import Effects from './Effects';
import {
  Position,
  DEFAULT_CONFIG,
  calculateNextPosition,
  getRandomPosition,
  checkCollision,
  checkWallCollision,
  checkSelfCollision
} from '../utils/gameUtils';

const shake = keyframes`
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
`;

const createGridBackground = () => {
  const size = DEFAULT_CONFIG.gridSize;
  return `
    background-size: ${size}px ${size}px;
    background-image:
      linear-gradient(to right, rgba(0, 0, 0, 0.05) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
  `;
};

const GameContainer = styled.div<{ isCollision: boolean }>`
  position: relative;
  width: ${DEFAULT_CONFIG.canvasWidth}px;
  height: ${DEFAULT_CONFIG.canvasHeight}px;
  border: 2px solid #333;
  background-color: #fff;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
  animation: ${props => props.isCollision ? shake : 'none'} 0.2s ease-in-out;
  ${createGridBackground()}
`;

const GameOverlay = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  color: white;
  font-size: 24px;
  z-index: 10;
`;

const Game: React.FC = () => {
  const { state, dispatch } = useGame();
  const [snake1, setSnake1] = useState<Position[]>([
    { x: 100, y: 100 },
    { x: 80, y: 100 },
    { x: 60, y: 100 },
  ]);
  const [snake2, setSnake2] = useState<Position[]>([
    { x: 500, y: 300 },
    { x: 520, y: 300 },
    { x: 540, y: 300 },
  ]);
  const [direction1, setDirection1] = useState<string>('RIGHT');
  const [direction2, setDirection2] = useState<string>('LEFT');
  const directionRef1 = useRef(direction1);
  const directionRef2 = useRef(direction2);
  const [food, setFood] = useState<Position>(getRandomPosition(DEFAULT_CONFIG));
  const [isCollision, setIsCollision] = useState(false);
  const [effectPosition, setEffectPosition] = useState<Position | null>(null);
  const [playSound] = useState(() => new Audio('/eat.mp3'));

  useEffect(() => {
    directionRef1.current = direction1;
    directionRef2.current = direction2;
  }, [direction1, direction2]);

  const generateFood = () => {
    let newFood: Position;
    do {
      newFood = getRandomPosition(DEFAULT_CONFIG);
    } while (
      snake1.some(segment => checkCollision(segment, newFood)) ||
      (state.mode === 'couple' && snake2.some(segment => checkCollision(segment, newFood)))
    );
    setFood(newFood);
  };

  const handleCollision = (player: number) => {
    setIsCollision(true);
    dispatch({ type: 'SET_STATE', payload: 'over' });
    if (state.mode === 'single' && player === 1) {
      const newHighScore = Math.max(state.score.player1, state.highScore);
      dispatch({ type: 'UPDATE_HIGH_SCORE', payload: newHighScore });
    }
    setTimeout(() => {
      setIsCollision(false);
    }, 200);
  };

  const handleFoodCollision = (head: Position, player: number) => {
    if (checkCollision(head, food)) {
      playSound.play().catch(() => {});
      setEffectPosition(food);
      generateFood();
      dispatch({
        type: 'UPDATE_SCORE',
        payload: { player, score: state.score[`player${player}`] + 1 }
      });
      return true;
    }
    return false;
  };

  const checkCollisions = (head: Position, body: Position[], otherSnake?: Position[]) => {
    if (checkWallCollision(head, DEFAULT_CONFIG)) {
      return true;
    }

    if (checkSelfCollision(head, body.slice(1))) {
      return true;
    }

    if (otherSnake && state.mode === 'couple') {
      if (otherSnake.some(segment => checkCollision(head, segment))) {
        return true;
      }
    }

    return false;
  };

  useEffect(() => {
    const handleKeyPress = (e: KeyboardEvent) => {
      const key = e.key.toUpperCase();

      if (key === 'P' && state.state === 'playing') {
        dispatch({ type: 'SET_STATE', payload: 'paused' });
        return;
      }

      if (key === 'P' && state.state === 'paused') {
        dispatch({ type: 'SET_STATE', payload: 'playing' });
        return;
      }

      if (key === 'R' && state.state === 'over') {
        dispatch({ type: 'RESET_GAME' });
        setSnake1([
          { x: 100, y: 100 },
          { x: 80, y: 100 },
          { x: 60, y: 100 },
        ]);
        setSnake2([
          { x: 500, y: 300 },
          { x: 520, y: 300 },
          { x: 540, y: 300 },
        ]);
        setDirection1('RIGHT');
        setDirection2('LEFT');
        generateFood();
        dispatch({ type: 'SET_STATE', payload: 'playing' });
        return;
      }

      if (state.state !== 'playing') return;

      // Player 1 controls (WASD)
      switch (key) {
        case 'W':
          if (directionRef1.current !== 'DOWN') setDirection1('UP');
          break;
        case 'S':
          if (directionRef1.current !== 'UP') setDirection1('DOWN');
          break;
        case 'A':
          if (directionRef1.current !== 'RIGHT') setDirection1('LEFT');
          break;
        case 'D':
          if (directionRef1.current !== 'LEFT') setDirection1('RIGHT');
          break;
      }

      // Player 2 controls (Arrow keys)
      if (state.mode === 'couple') {
        switch (e.key) {
          case 'ArrowUp':
            if (directionRef2.current !== 'DOWN') setDirection2('UP');
            break;
          case 'ArrowDown':
            if (directionRef2.current !== 'UP') setDirection2('DOWN');
            break;
          case 'ArrowLeft':
            if (directionRef2.current !== 'RIGHT') setDirection2('LEFT');
            break;
          case 'ArrowRight':
            if (directionRef2.current !== 'LEFT') setDirection2('RIGHT');
            break;
        }
      }
    };

    window.addEventListener('keydown', handleKeyPress);
    return () => window.removeEventListener('keydown', handleKeyPress);
  }, [state.state, state.mode]);

  useEffect(() => {
    if (state.state !== 'playing') return;

    const moveSnakes = () => {
      // Move snake 1
      setSnake1(prevSnake => {
        const newHead = calculateNextPosition(
          prevSnake[0],
          directionRef1.current,
          DEFAULT_CONFIG.gridSize
        );

        if (checkCollisions(newHead, prevSnake, state.mode === 'couple' ? snake2 : undefined)) {
          handleCollision(1);
          return prevSnake;
        }

        // Check if snake ate food
        if (handleFoodCollision(newHead, 1)) {
          return [newHead, ...prevSnake];
        }

        return [newHead, ...prevSnake.slice(0, -1)];
      });

      // Move snake 2 in couple mode
      if (state.mode === 'couple') {
        setSnake2(prevSnake => {
          const newHead = calculateNextPosition(
            prevSnake[0],
            directionRef2.current,
            DEFAULT_CONFIG.gridSize
          );

          if (checkCollisions(newHead, prevSnake, snake1)) {
            handleCollision(2);
            return prevSnake;
          }

          // Check if snake ate food
          if (handleFoodCollision(newHead, 2)) {
            return [newHead, ...prevSnake];
          }

          return [newHead, ...prevSnake.slice(0, -1)];
        });
      }
    };

    const gameLoop = setInterval(moveSnakes, DEFAULT_CONFIG.initialSpeed);
    return () => clearInterval(gameLoop);
  }, [state.state, state.mode, food, snake1, snake2]);

  return (
    <GameContainer isCollision={isCollision}>
      <Snake
        segments={snake1}
        color="#ff69b4"
        gridSize={DEFAULT_CONFIG.gridSize}
      />
      {state.mode === 'couple' && (
        <Snake
          segments={snake2}
          color="#4169e1"
          gridSize={DEFAULT_CONFIG.gridSize}
        />
      )}
      <Food
        position={food}
        size={DEFAULT_CONFIG.gridSize}
      />
      <ScoreBoard />
      {state.state === 'start' && <StartMenu />}
      {state.state === 'paused' && <PauseMenu />}
      {state.state === 'over' && (
        <GameOverlay>
          <h2>游戏结束</h2>
          {state.mode === 'couple' ? (
            <>
              <p>玩家1得分: {state.score.player1}</p>
              <p>玩家2得分: {state.score.player2}</p>
              <p>
                {state.score.player1 > state.score.player2
                  ? '玩家1获胜！'
                  : state.score.player1 < state.score.player2
                  ? '玩家2获胜！'
                  : '平局！'}
              </p>
            </>
          ) : (
            <>
              <p>得分: {state.score.player1}</p>
              <p>最高分: {state.highScore}</p>
            </>
          )}
          <p>按 R 键重新开始</p>
        </GameOverlay>
      )}
      {effectPosition && <Effects position={effectPosition} />}
    </GameContainer>
  );
};

export default Game; 